#include <coroutine>
#include <iostream>
#include <memory>

class Generator
{
public:
    struct promise_type
    {
        std::shared_ptr<int> ptr = std::make_shared<int>(0);

        Generator get_return_object()
        {
            return Generator{std::coroutine_handle<promise_type>::from_promise(*this)};
        }
        std::suspend_always initial_suspend() noexcept { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }

        std::suspend_always yield_value(int v)
        {
            *ptr = v;
            return {};
        }
        void return_void() {}
        void unhandled_exception() { std::terminate(); }
    };

    using handle_type = std::coroutine_handle<promise_type>;

    explicit Generator(handle_type h) : handle(h) {}
    ~Generator()
    {
        if (handle)
            handle.destroy();
    }

    /* === 用户接口 === */
    bool next()
    {
        if (!handle.done())
        {
            handle.resume();
            return !handle.done();
        }
        return false;
    }

    int value() const { return *handle.promise().ptr; }

private:
    handle_type handle;
};

Generator counter()
{
    for (int i = 1; i <= 5; ++i)
        co_yield i;
}

/* === 演示 === */
int main()
{
    // 1、主线程执行 auto gen = counter();，触发编译器生成协程帧对象。
    // 2、编译器在协程帧内先构造 promise_type 实例。
    // 3、promise_type 立即执行 get_return_object()，用 from_promise 拿到句柄，构造 Generator 返回给主线程。
    // 4、接着执行 initial_suspend()，返回 suspend_always，协程在第一条语句前暂停。
    // 5、主线程拿到 gen 对象，但协程尚未进入 for 循环；主线程开始 while (gen.next()) …
    // 6、第一次 gen.next() 内部调用 handle.resume()，协程从暂停点继续，真正进入 for (int i = 1; …)。
    // 7、遇到 co_yield i;，编译器转调 promise.yield_value(i)，把值写进 *ptr 并再次暂停。
    // 8、resume 返回，主线程发现未 done()，于是取出 *ptr 打印；循环重复 6–7–8 直到 i = 5 结束。
    //     auto gen = counter();
    while (gen.next())
        std::cout << gen.value() << ' ';
    std::cout << '\n';
}